package com.hunliji.monitor.web.facade.impl;

import com.alibaba.fastjson.JSON;
import com.hunliji.common.exception.WarnException;
import com.hunliji.monitor.service.api.*;
import com.hunliji.monitor.service.api.model.bo.*;
import com.hunliji.monitor.service.api.model.param.QueryChatGroupParam;
import com.hunliji.monitor.service.api.model.param.QueryInformActionStrategyParam;
import com.hunliji.monitor.share.enums.SeverityEnum;
import com.hunliji.monitor.web.facade.InformFacade;
import com.hunliji.monitor.web.model.param.*;
import com.hunliji.monitor.web.strategy.inform.FeiShuChatInformAction;
import com.hunliji.monitor.web.strategy.inform.model.InformDescription;
import com.hunliji.monitor.web.strategy.inform.model.InformTouching;
import javassist.SerialVersionUID;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 通知
 * @author wuchen
 */
@Service
public class InformFacadeImpl implements InformFacade {
    private static final Logger logger = LoggerFactory.getLogger(InformFacadeImpl.class);
    @Resource
    private AlertConfigService alertConfigService;
    @Resource
    private AlertChatBindService alertChatBindService;
    @Resource
    private FeiShuChatInformAction feiShuChatInformAction;
    @Resource
    private ChatGroupService chatGroupService;
    @Resource
    private InformActionStrategyService informActionStrategyService;
    @Resource
    private UserInfoService userInfoService;
    @Override
    public void inform(InformParam informParam) {
        //查询告警
        AlertConfigBO alertConfigBO = queryAlertConfig(informParam.getAlertId(),informParam.getProject(),informParam.getAlertName());
        //查询和告警群聊的绑定关系
        //todo 目前默认只有群聊，这部分逻辑后续需要调整
        List<AlertChatBindBO> alertChatBindBOList = alertChatBindService.listByQuery(alertConfigBO.getId(),null);
        if(CollectionUtils.isEmpty(alertChatBindBOList)){
            return;
        }
        //群聊查询
        List<Long> chatGroupIds = alertChatBindBOList.stream().map(AlertChatBindBO::getChatGroupId)
                .collect(Collectors.toList());
        Map<Long, ChatGroupBO> chatGroupBOMap = chatGroupService.getMapByIds(chatGroupIds);
        //循环处理
        for (AlertChatBindBO alertChatBindBO:alertChatBindBOList){
            //获取群聊
            ChatGroupBO chatGroupBO = chatGroupBOMap.get(alertChatBindBO.getChatGroupId());
            if(Objects.isNull(chatGroupBO)){
                continue;
            }
            //查询行动策略
            QueryInformActionStrategyParam queryInformActionStrategyParam = QueryInformActionStrategyParam.build(alertChatBindBO.getId(),informParam.getInformKey(),informParam.getSeverity());
            List<InformActionStrategyBO> informActionStrategyBOList = informActionStrategyService.query(queryInformActionStrategyParam);

            InformDescription informDescription = new InformDescription();
            informDescription.setTitle(informParam.getTitle());
            informDescription.setMsg(informParam.getMsg());
            if(StringUtils.isNotBlank(informParam.getExtra())){
                try{
                    informDescription.setExtra(JSON.parseObject(informParam.getExtra(),Map.class));
                }catch (Exception e){
                    logger.warn("无法识别extra字段，该字段被排除");
                }
            }

            InformTouching informTouching = new InformTouching();
            //如果在行动策略中配置了群，则走具体的群，否则走外部配置的群
            if(!CollectionUtils.isEmpty(informActionStrategyBOList)){
                for (InformActionStrategyBO informActionStrategyBO:informActionStrategyBOList){
                    if(Objects.nonNull(informActionStrategyBO.getUserGroupId())){
                        chatGroupBO = chatGroupService.queryById(informActionStrategyBO.getUserGroupId());
                        break;
                    }
                }
            }
            //当没有@对象的时候，最低告警级别是高
            if(CollectionUtils.isEmpty(informActionStrategyBOList) && informParam.getSeverity() < SeverityEnum.HIGH.getCode()){
                continue;
            }
            informTouching.setPlatformId(chatGroupBO.getFeiShuChatId());
            informTouching.setSeverity(informParam.getSeverity());
            informTouching.setInformActionStrategyBOList(informActionStrategyBOList);
            feiShuChatInformAction.inform(informTouching,informDescription);
        }
    }

    @Override
    public void updateInformChatGroup(AddOrUpdateInformChatGroupParam addOrUpdateInformChatGroupParam) {
        //根据群名称去检索群
        QueryChatGroupParam queryChatGroupParam = new QueryChatGroupParam();
        queryChatGroupParam.setName(addOrUpdateInformChatGroupParam.getChatGroupName());
        List<ChatGroupBO> chatGroupBOList =  chatGroupService.query(queryChatGroupParam);
        if(CollectionUtils.isEmpty(chatGroupBOList)){
            throw new WarnException("无法查询到对应群");
        }
        if(chatGroupBOList.size()>1){
            throw new WarnException("根据名称检索群数量大于1，无法完成绑定");
        }
        ChatGroupBO chatGroupBO = chatGroupBOList.get(0);
        //查询策略
        QueryInformActionStrategyParam queryInformActionStrategyParam = new QueryInformActionStrategyParam();
        queryInformActionStrategyParam.setActionStrategyKey(addOrUpdateInformChatGroupParam.getServerName());
        List<InformActionStrategyBO> informActionStrategyBOList =  informActionStrategyService.query(queryInformActionStrategyParam);
        if(CollectionUtils.isEmpty(informActionStrategyBOList)){
            throw new WarnException("当前无策略，请联系无尘进行策略配置");
        }
        for (InformActionStrategyBO informActionStrategyBO:informActionStrategyBOList){
            informActionStrategyBO.setUserGroupId(chatGroupBO.getId());
            informActionStrategyService.updateById(informActionStrategyBO);
        }
    }

    @Override
    public void addInformAt(AddOrUpdateInformAtParam addOrUpdateInformAtParam) {
        if(StringUtils.isBlank(addOrUpdateInformAtParam.getServerName()) || StringUtils.isBlank(addOrUpdateInformAtParam.getUserName())){
            throw new WarnException("服务名称和用户名称不能为空，请检查后重试");
        }
        //去检索用户
        List<UserInfoBO> userInfoBOList = userInfoService.getListByQuery(addOrUpdateInformAtParam.getUserName(),null);
        if(CollectionUtils.isEmpty(userInfoBOList)){
            throw new WarnException("无法查询到对应用户，请按照接口去初始化用户：");
        }
        if(userInfoBOList.size()>1){
            throw new WarnException("根据名称检索用户数量大于1，无法完成绑定");
        }
        UserInfoBO userInfoBO = userInfoBOList.get(0);
        //查询当前策略
        List<Integer> severityList = addOrUpdateInformAtParam.getSeverityList();
        if(CollectionUtils.isEmpty(severityList)){
            severityList = Arrays.asList(6,8,10);
        }
        for (Integer severity:severityList){
            QueryInformActionStrategyParam queryInformActionStrategyParam = new QueryInformActionStrategyParam();
            queryInformActionStrategyParam.setActionStrategyKey(addOrUpdateInformAtParam.getServerName());
            queryInformActionStrategyParam.setSeverity(severity);
            List<InformActionStrategyBO> informActionStrategyBOList =  informActionStrategyService.query(queryInformActionStrategyParam);
            //如果为空，则添加
//            if(CollectionUtils.isEmpty(informActionStrategyBOList)){
                InformActionStrategyBO informActionStrategyBO = new InformActionStrategyBO();
                informActionStrategyBO.setAlertChatBindId(21L);
                informActionStrategyBO.setActionStrategyKey(addOrUpdateInformAtParam.getServerName());
                informActionStrategyBO.setUserId(userInfoBO.getId());
                informActionStrategyBO.setActionStrategyType("feishu_chat");
                informActionStrategyBO.setSeverity(severity);
                informActionStrategyService.save(informActionStrategyBO);
//            }
        }
    }

    @Override
    public void updateInformAt(UpdateInformAtParam updateInformAtParam) {
        List<UserInfoBO> userInfoBOList = userInfoService.getListByQuery(updateInformAtParam.getUserName(),null);
        if(CollectionUtils.isEmpty(userInfoBOList)){
            throw new WarnException("无法查询到对应用户，请按照接口去初始化用户：");
        }
        if(userInfoBOList.size()>1){
            throw new WarnException("根据名称检索用户数量大于1，无法完成绑定");
        }
        UserInfoBO userInfoBO = userInfoBOList.get(0);
        InformActionStrategyBO informActionStrategyBO = informActionStrategyService.queryById(updateInformAtParam.getId());
        if(Objects.isNull(informActionStrategyBO)){
            return;
        }
        informActionStrategyBO.setUserId(userInfoBO.getId());
        informActionStrategyService.updateById(informActionStrategyBO);
    }

    @Override
    public void delInformAt(UpdateInformAtParam updateInformAtParam) {
        InformActionStrategyBO informActionStrategyBO = informActionStrategyService.queryById(updateInformAtParam.getId());
        if(Objects.isNull(informActionStrategyBO)){
            return;
        }
        informActionStrategyBO.setDeleted(Boolean.TRUE);
        informActionStrategyService.updateById(informActionStrategyBO);
    }

    private AlertConfigBO queryAlertConfig(String alertId,String project,String alertName){
        AlertConfigBO alertConfigBO = alertConfigService.getByQuery(
                AlertConfigBO.builder().alertId(alertId).project(project).build());
        if(Objects.isNull(alertConfigBO)){
            alertConfigBO = AlertConfigBO.builder()
                    .alertId(alertId)
                    .project(project)
                    .alertName(alertName)
                    .actionTypes("")
                    .minActionSeverity(0)
                    .build();
            logger.info("发现接入新告警，向数据库插入新数据，{}", JSON.toJSONString(alertConfigBO));
            alertConfigService.insertOne(alertConfigBO);
        } else {
            alertConfigBO.setAlertName(alertName);
            alertConfigService.updateOne(alertConfigBO);
        }
        return alertConfigBO;
    }
}
